/*

  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  
           http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is Indigo framework applicatif.
  
  The Initial Developer of the Original Code is
  Olivier Bugalotto (aka Iteratif) <olivier.bugalotto@iteratif.net>.
  Portions created by the Initial Developer are Copyright (C) 2004-2008
  the Initial Developer. All Rights Reserved.
  
  Contributor(s) :
  
*/
package indigo.context
{
	import indigo.descriptors.ApplicationContextDescriptor;
	import indigo.descriptors.DescriptorLoader;
	import indigo.descriptors.IDescriptor;
	import indigo.descriptors.IDescriptorLoader;
	import indigo.events.QueueEvent;
	import indigo.modules.ModulesManager;
	import indigo.net.QueueLoader;
	import indigo.register.IObjectDefinitionRegistry;
	import indigo.register.ObjectDefinitionRegistry;


	/**
	 * The class <code>ApplicationContext</code> is a factory of objects that allows 
	 * to instantiate objects from a dictionary definitions of object 
	 * configurable from an XML configuration file called "descriptor"
	 * 
	 * La classe <code>ApplicationContext</code> est une fabrique d'objets qui permet
 	 * d'instancier des objets a partir d'un dictionnaire de definitions d'objet
 	 * configurable depuis un fichier de configuration XML appelé "descripteur".
 	 * 
 	 * @example the following example you show how to use this class with AIR
 	 * Cet exemple presente l'utilisation de la classe <code>ApplicationContext</code>
 	 * avec AIR:
 	 * <br>
 	 * Descripteur de configuration <i>indigo-config.xml</i>:
 	 * <listing version="3.0">
 	 * &lt;?xml version="1.0" encoding="utf-8"?&gt;
 	 * &lt;objects xmlns="http://www.indigo-framework.org"&gt;
 	 * 		&lt;object id="httpService" type="org.iteratif.services.HTTPConnection"&gt;
 	 * 			&lt;property name="url" value="http://www.monservice.com" /&gt;
 	 * 			&lt;property name="method" value="GET" /&gt;
 	 * 		&lt;/object&gt;
 	 * &lt;/objects&gt;
 	 * </listing>
	 * 
	 * Pour recuperer une instance de l'objet d'identifiant <i>httpService</i>
	 * a partir de <code>ApplicationContext</code>:
	 * 
	 * <listing version="3.0">
	 * <b>var</b> factory:IContext = ContextManager.getContext();
	 * <b>var</b> http:IHTTP = factory.getObject("httpService") <b>as</b> IHTTP;
	 * trace(http.url); // http://www.monservice.com
	 * </listing>
	 * 
	 * @see indigo.register.ObjectDefinitionRegistry
	 * @see IContext
	 */
	public class ApplicationContextImpl
	{
		private var _callbackReady:Function;
		private var _descriptorLoader:IDescriptorLoader;
		
		public function get descriptorLoader():IDescriptorLoader {
			if(!_descriptorLoader) {
				_descriptorLoader = new DescriptorLoader();
			}
			return _descriptorLoader;
		}
		
		public function set descriptorLoader(value:IDescriptorLoader):void {
			if(value != _descriptorLoader) {
				_descriptorLoader = value;
			}
		}
		
		public var url:String = "app-config.xml";
		
		public function ApplicationContextImpl() {
			
		}
		
		public function start(callbackReady:Function):void {
			if(!url) throw new ArgumentError("L'argument url ne peut pas être null : [object XmlApplicationContext]"); 
			if(callbackReady == null) throw new ArgumentError("La méthode de callbackReady ne peut pas être null : [object XmlApplicationContext]");
			
			_callbackReady = callbackReady;
			descriptorLoader.load(url, onDescriptorReady);
		}
		
		private function onDescriptorReady(datas:Object):void {
			var config:XML = XML(datas);
			
			var register:IObjectDefinitionRegistry = new ObjectDefinitionRegistry();
			var readerDescriptor:IDescriptor = new ApplicationContextDescriptor(register);
			readerDescriptor.parse(config);
			
			var context:IApplicationContext = new XmlApplicationContext("context",register);
			ContextManager.registerContext(context);
			
			// TODO: gestion du chargement des modules externes
			// utilisation de la classe ModuleManager
			if(ModulesManager.numModules > 0) {
				var queueLoader:QueueLoader = new QueueLoader();
				queueLoader.addEventListener(QueueEvent.READY,onModuleReady);
				queueLoader.load(ModulesManager.modules);
			} else {
				_callbackReady();
			}
		}
		
		private function onModuleReady(e:QueueEvent):void {
			_callbackReady();
		}
	}
}